﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Administration.Health;
using SDS.SPHealthAnalyzerRules.Delegation.Helpers;

namespace SDS.SPHealthAnalyzerRules.Delegation.Rules
{
    /// <summary>
    /// Recommends that the C2WTS not run as the local system.
    /// </summary>
    public class C2WTS_NotUsing_LocalSystem : SPHealthAnalysisRule
    {
        private Guid CorrelationToken = Guid.NewGuid();

        readonly private List<string> Errors = new List<string>();
        readonly private List<string> Remedies = new List<string>();

        public override SPHealthCategory Category { get { return SPHealthCategory.Configuration; } }
        public override SPHealthCheckErrorLevel ErrorLevel { get { return SPHealthCheckErrorLevel.Information; } }

        public override SPHealthAnalysisRuleAutomaticExecutionParameters AutomaticExecutionParameters
        {
            get
            {
                return new SPHealthAnalysisRuleAutomaticExecutionParameters()
                {
                    Schedule = SPHealthCheckSchedule.Daily,
                    Scope = SPHealthCheckScope.Any,
                    ServiceType = SPFarm.Local.Services.First(s => s.Name == "c2wts").GetType(),     // run on any server running C2WTS
                    RepairAutomatically = false
                };
            }
        }

        public override SPHealthCheckStatus Check()
        {
            // return variable, defualt value
            SPHealthCheckStatus outval = SPHealthCheckStatus.Failed;

            // log
            LoggingService.Write(LoggingService.Category_C2WTS, TraceSeverity.Verbose, "Executing Health Check", CorrelationToken);

            // running as the system account
            Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(delegate { outval = doCheck(); });
            
            // log
            LoggingService.Write(
                LoggingService.Category_C2WTS,
                TraceSeverity.Verbose,
                String.Format("Health Check completed with outcome {0}", outval.ToString()),
                CorrelationToken);

            return outval;
        }

        public override string Summary { get { return "DELEGATION: Claims to Windows Token Service is running as Local System"; } }
        public override string Explanation
        {
            get {
                return String.Format(
                    @"{0}It is recommended that the Claims to Windows Token Service (C2WTS) execute using its own dedicated domain account." +
                    @"{0}" +
                    @"{0}Due to the privileges and restricted configuration required for the execution of the C2WTS, it is recommended that a domain account be used. By doing so, all configuration will be reused across servers." +
                    @"{0}" +
                    @"{0}By continuing use of the Local System, delegation settings will need to be replicated among all computer accounts running the C2WTS.",
                    
                    Environment.NewLine
                    ).Trim();
            }
        }
        public override string Remedy
        {
            get { return String.Format("Configure the Claims to Windows Token Service to use a dedicated domain account"); }
        }



        private SPHealthCheckStatus doCheck()
        {
            try
            {
                // this was in case I wanted to include the server count in the explanation
                //   to add emphasis to the manual effort required by continuing use of LocalSystem
                //var C2WTS_Servers = SPFarm.Local.Servers.Where(s => s.ServiceInstances.Any(si => si.Service.Name == "c2wts"));
                //var C2WTS_Servers_Count = C2WTS_Servers.Count();

                string SvcRunsAs_Raw = Helpers.Win32API.SvcConfigMgr.GetServiceAccount_W2CTS();
                return (SvcRunsAs_Raw.ToLower() == "LocalSystem".ToLower())
                     ? SPHealthCheckStatus.Failed
                     : SPHealthCheckStatus.Passed;
                
            } // try
            catch (Exception ex)
            {
                LoggingService.Write(
                    LoggingService.Category_C2WTS,
                    TraceSeverity.High,
                    String.Format("Health Check encountered the following exception: {0}", ex.Message),
                    CorrelationToken);

                return SPHealthCheckStatus.Failed;
            }

        } // doCheck()

    } // class
} // namespace
